package model.playable.unit;
import java.util.List;

import model.command.*;
import model.playable.*;
import model.map.Direction;
import model.map.GameTile;
import model.mapping.*;

public abstract class Unit extends Playable implements Moveable, Loadable
{
	int armyId;
	int rallyPointId;
	int vehicleId;
	int movementSpeed;
	boolean isBattleGroup;
	boolean isReinforcement;
	private List<String> allowedWalkableTerrains;
	
	public void setWalkableTerrains(List<String> walkableTerrains)
	{
		allowedWalkableTerrains = walkableTerrains;
	}
	
	public int getArmyId()
	{
		return armyId;
	}
	
	public void setArmyId(int armyId)
	{
		this.armyId = armyId;
	}
	
	public int getVehicleId()
	{
		return vehicleId;
	}
	
	public void setVehicleId(int vehicleId)
	{
		this.vehicleId = vehicleId;
	}
	
	public int getRallyPointId()
	{
		return rallyPointId;
	}
	
	public void setRallyPointId(int rallyPointId)
	{
		this.rallyPointId = rallyPointId;
	}
	
	public int getMovementSpeed()
	{
		return movementSpeed;
	}
	
	public void setMovementSpeed(int movementSpeed)
	{
		this.movementSpeed = movementSpeed;
	}
	
	public boolean getIsBattleGroup()
	{
		return isBattleGroup;
	}
	
	public void setIsBattleGroup(boolean isBattleGroup)
	{
		this.isBattleGroup = isBattleGroup;
	}
	
	public boolean getIsReinforcement()
	{
		return isReinforcement;
	}
	
	public void setIsReinforcement(boolean isReinforcement)
	{
		this.isReinforcement = isReinforcement;
	}
	
	public void incrementMovementSpeed(int increment)
	{
		movementSpeed += increment;
	}
	
	public void move(Direction direction)
	{
		PlayableMapping map = PlayableMapping.getPlayableMapping();
		GameTile tile = map.getLocationOfUnit(this);
		GameTile neighbor = tile.getNeighborAt(direction);
		if ((neighbor != null) && !map.isObstructedForPlayer(neighbor, getPlayer()) && isWalkable(neighbor.getTerrainType()))
		{
			map.removeUnit(this);
			map.addUnit(neighbor, this);
			System.out.println("This unit executed move " + direction.toString() );
		}
		else
		{
			System.out.println("This unit cannot move " + direction.toString());
		}
	}
	
	public boolean isWalkable(String terrainType)
	{
		return allowedWalkableTerrains.contains(terrainType);
	}

	public void powerUp()
	{
		setIsPoweredDown(false);
		System.out.println("The unit is now powered up");
	}
	
	public void powerDown()
	{
		setIsPoweredDown(true);
		System.out.println("The unit is now powered down");
	}
	
	public void decommission()
	{
		setIdNumber(-1);
		System.out.println("The unit is now decommissioned");
	}
	
	public void standBy()
	{
		setIsInStandBy(true);
		System.out.println("The unit is now in stand by");
	}

	public void load()
	{
		PlayableMapping map = PlayableMapping.getPlayableMapping();
		GameTile tile = map.getLocationOfUnit(this);
		if(!map.getVehiclesOn(tile).isEmpty())
		{
			Vehicle vehicle = map.getFirstAvailableVehicleOn(tile);
			map.removeUnit(this);
			vehicle.loadPassenger(this);
		}
		System.out.println("The unit is now loaded");
	}
	
	public String toString()
	{
		return "Unit";
	}
}